
//
// 101206a- AH     - Created.
// 101206b- AH     - Create(String, Tree).
// 101206c- AH     - Now implements new interface TreeCreator.
// 101214a- AH/LLC - (Hector) Took in use SoekratTreeCellRenderer. 
// 101214b- AH/LLC - (Hector) Create tree action got a icon designed by
//                   Laetitia. 
// 101220 - AH     - Remove button.
// 101224 - AH     - Shows comment for selected Tree. 
// 101225a- AH     - Edit button.
// 101225c- AH     - Fixed so only one Tree can be selected.
// 101225d- AH     - TreeCreatorDialog constructor now need SoekratEngine to be
//                   passed.
// 101225e- AH     - EditTreeDialog constructor now need SoekratEngine to be
//                   passed.
// 101225f- AH     - HistoricalEvent object is generated when Tree is removed.
// 110423 - AH     - No more direct access to ontology on SoekratEngine, must
//                   use getWheel() first to get.
// 110518 - AH     - Create Root button.
// 110614a- AH     - Made tree editable and took in use new class 
//                   SoekratTreeCellEditor.
// 110614b- AH     - Now that can edit directly in tree view Create actions
//                   does not pop up dialogs.
//

package org.soekrat.gui.swing.forest;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import org.soekrat.engine.Soekrat2Engine;
import org.soekrat.engine.forest.Forest;
import org.soekrat.engine.forest.Tree;

/**
 * <p>
 *   Tree view of
 *   {@link Forest}.
 * </p>
 * @author Arne Halvorsen (AH)
 * @author Laetitia Le Chatton (LLC) 
 */
@SuppressWarnings("serial")
public final class ForestTreePanel extends JPanel implements TreeCreator
{
  private final Soekrat2Engine m_engine;
  
  private ForestTreeModel m_model=ForestTreeModel.EMPTY;
  
  private final JTree m_tree=new JTree(m_model);
  
  //private TreeCreatorDialog m_tcd=null;
  
  private final CommentViewDialog m_nvd=new CommentViewDialog();
  
  private final EditTreeDialog m_etd;
  
  /**
   * <p>
   *   Constructor.
   * </p>
   * @param engine Engine interfaced. 
   */
  public ForestTreePanel(Soekrat2Engine engine)
  {
    if (engine==null)
    {
      throw new NullPointerException("engine");
    }
    
    m_engine=engine;
    
    m_etd=new EditTreeDialog(engine);
    
    setLayout(new BorderLayout());
    
    
    
    JPanel north=new JPanel(new FlowLayout(FlowLayout.CENTER));
    north.add(new JLabel("Forest", JLabel.CENTER));
    add(north, BorderLayout.NORTH);
    
    m_tree.addTreeSelectionListener
    (
      new TreeSelectionListener() 
      {
        public void valueChanged(TreeSelectionEvent e)
        {
          m_nvd.showDialog(getSelected());
        }
      }
    );
    
    m_tree.setEditable(true);
    m_tree.getSelectionModel().setSelectionMode(
      TreeSelectionModel.SINGLE_TREE_SELECTION);
    m_tree.setCellRenderer(SoekratTreeCellRenderer.INSTANCE);
    m_tree.setCellEditor(new SoekratTreeCellEditor(m_tree));
    m_tree.setShowsRootHandles(true);
    m_tree.setRootVisible(false);
    add(new JScrollPane(m_tree), BorderLayout.CENTER);
    
    setForest(m_engine.getWheel().getForest());
    
    JPanel m_buttons=new JPanel(new FlowLayout(FlowLayout.CENTER));
    
    m_buttons.add
    (
      new JButton // Create Tree Action.
      (
        new AbstractAction("Create Root") 
        {
          public void actionPerformed(ActionEvent e)
          {
            m_model.create(null);
            //if (m_tcd==null) m_tcd=new TreeCreatorDialog(m_model, m_engine);
            //m_tcd.showDialog(null);
          }
        }
      )
    );
    
    m_buttons.add
    (
      new JButton // Create Tree Action.
      (
        new AbstractAction("Create") 
        {
          /*{
            URL url=getClass().getResource(
              "/org/soekrat/gui/swing/icons/treeButtons.png");
            ImageIcon icon=new ImageIcon(url); 
            putValue(SMALL_ICON, icon);  
          }*/
          
          public void actionPerformed(ActionEvent e)
          {
            Tree tree=getSelected();
            m_model.create(tree);
            
            //if (m_tcd==null) m_tcd=new TreeCreatorDialog(m_model, m_engine);
            //m_tcd.showDialog(getSelected());
          }
        }
      )
    );
    
    m_buttons.add
    (
      new JButton // Edit Tree Action.
      (
        new AbstractAction("Edit") 
        {
          {
            setEnabled(false);
            m_tree.addTreeSelectionListener
            (
              new TreeSelectionListener() 
              {
                public void valueChanged(TreeSelectionEvent e)
                {
                  setEnabled(getSelected()!=null);
                }
              }
            );
            /*
            URL url=getClass().getResource(
              "/org/soekrat/gui/swing/icons/treeButtons.png");
            ImageIcon icon=new ImageIcon(url); 
            putValue(SMALL_ICON, icon);
            */  
          }
          
          public void actionPerformed(ActionEvent e)
          {
            Tree selected=getSelected();
            if (selected!=null)
            {
              if (m_etd.showDialog(selected)) m_model.treeChanged(selected);
            }
          }
        }
      )
    );
    
    m_buttons.add
    (
      new JButton // Remove Tree Action.
      (
        new AbstractAction("Remove") 
        {
          {
            setEnabled(false);
            m_tree.addTreeSelectionListener
            (
              new TreeSelectionListener() 
              {
                public void valueChanged(TreeSelectionEvent e)
                {
                  setEnabled(getSelected()!=null);
                }
              }
            );
            /*
            URL url=getClass().getResource(
              "/org/soekrat/gui/swing/icons/treeButtons.png");
            ImageIcon icon=new ImageIcon(url); 
            putValue(SMALL_ICON, icon);
            */  
          }
          
          public void actionPerformed(ActionEvent e)
          {
            Tree selected=getSelected();
            if (selected!=null)
            {
              m_model.remove(selected);
            }
          }
        }
      )
    );
    
    add(m_buttons, BorderLayout.SOUTH);
  }
  
  /**
   * <p>
   *   Sets
   *   {@link Forest} to view.
   * </p>
   * @param forest {@code Forest} or {@code null} if to clear view.
   */
  public void setForest(Forest forest)
  {
    if (forest!=m_model.getRoot())
    {
      m_model=(forest==null) ? 
        ForestTreeModel.EMPTY : new ForestTreeModel(forest);
      m_tree.setModel(m_model);
    }
  }
  
  /**
   * <p>
   *   Gets selected
   *   {@link Tree}.
   * </p>
   * @return Selected or {@code null} if no
   *         {@link Tree} selected.
   */
  public Tree getSelected()
  {
    TreePath path=m_tree.getSelectionPath();
    Object selected=(path==null || path.getPathCount()==0) ? 
      null : path.getLastPathComponent();
    return selected instanceof Tree ? (Tree)selected : null;
  }
  
  /**
   * <p>
   *   Creates 
   *   {@link Tree}.
   * </p>
   * @param name   Name of tree to create.
   * @param parent Parent, if {@code null} creates new root.
   * @return Created.
   * @throws IllegalArgumentException If {@code this} has the empty tree model.
   */
  public Tree create(String name, Tree parent)
  {
    if (name==null)
    {
      throw new NullPointerException("name");
    }
    if (parent==null)
    {
      throw new NullPointerException("parent");
    }
    
    return m_model.create(name, parent);
  }
  
}
